// type DateOrStr = Date|string;

interface IDateFormat {
    isLeapYear(date: Date): boolean;
    format(date: Date, formatStr: string): string;
    checkValid(dateStr: string): boolean;
    checkTimeValid(dateStr: string): boolean;
    datePart(date: Date): IDateOb;
    // getNow<T extends DateOrStr>(date: T): T;
}

export interface IDateOb {
    year: number;// 年
    month: number;// 月
    date: number;// 日期
    hours: number;// 小时
    minutes: number;// 分钟
    seconds: number;// 秒
    day: number;// 周几
}

interface IWeek {
    [index: number]: string;
}

const Week: IWeek = ["日","一","二","三","四","五","六"];

export class DateFormat implements IDateFormat {
    /**
     * 是否闰年
     * @param date
     */
    public isLeapYear(date: Date): boolean {
        return 0 === date.getFullYear() % 4 && (( date.getFullYear() % 100 !== 0 ) || ( date.getFullYear() % 400 === 0 ));
    }
    /**
     * 日期格式化
     * 格式 YYYY/yyyy/YY/yy 表示年份
     * MM/M 月份
     * W/w 星期
     * dd/DD/d/D 日期
     * hh/HH/h/H 时间
     * mm/m 分钟
     * ss/SS/s/S 秒
     * @param date Date
     * @param formatStr string
     */
    public format(date: Date, formatStr: string): string {
        let str: string = formatStr;
        str = str.replace(/yyyy|YYYY/, `${date.getFullYear()}`);
        str = str.replace(/yy|YY/, (date.getFullYear() % 100) > 9 ? (date.getFullYear() % 100).toString() : '0' + (date.getFullYear() % 100));
        const month: number = date.getMonth() + 1;
        str = str.replace(/MM/, month > 9 ? month.toString() : '0' + month);
        str = str.replace(/M/g, `${month}`);
        str = str.replace(/w|W/g, Week[date.getDay()]);
        str = str.replace(/dd|DD/, date.getDate() > 9 ? date.getDate().toString() : '0' + date.getDate());
        str = str.replace(/d|D/g, `${date.getDate()}`);
        str = str.replace(/hh|HH/, date.getHours() > 9 ? date.getHours().toString() : '0' + date.getHours());
        str = str.replace(/h|H/g, `${date.getHours()}`);
        str = str.replace(/mm/, date.getMinutes() > 9 ? date.getMinutes().toString() : '0' + date.getMinutes());
        str = str.replace(/m/g, `${date.getMinutes()}`);
        str = str.replace(/ss|SS/, date.getSeconds() > 9 ? date.getSeconds().toString() : '0' + date.getSeconds());
        str = str.replace(/s|S/g, `${date.getSeconds()}`);

        return str;
    }
    /**
     * 日期合法性验证
     * 格式为：YYYY-MM-DD或YYYY/MM/DD
     * @param dateStr string
     */
    public checkValid(dateStr: string): boolean {
        const sDate: string = dateStr.replace(/(^\s+|\s+$)/g,'');
        if(sDate==='') { return true };
        const s: string = sDate.replace(/[\d]{ 4,4 }[\-/]{ 1 }[\d]{ 1,2 }[\-/]{ 1 }[\d]{ 1,2 }/g,'');
        if (s === '') // 说明格式满足YYYY-MM-DD或YYYY-M-DD或YYYY-M-D或YYYY-MM-D
        {
            const t: Date = new Date(sDate.replace(/\-/g, '/'));
            const ar: string[] = sDate.split(/[-/:]/);
            if (ar[0] !== `${t.getFullYear()}` || ar[1] !== `${t.getMonth() + 1}` || ar[2] !== `${t.getDate()}`) {
                return false;
            }
        }
        else {
            return false;
        }
        return true;
    }
    /**
     * 日期时间检查
     * 格式为：YYYY-MM-DD HH:MM:SS
     * @param dateStr string
     */
    public checkTimeValid(dateStr: string): boolean {
        const reg: RegExp = /^(\d+)-(\d{ 1,2 })-(\d{ 1,2 }) (\d{ 1,2 }):(\d{ 1,2 }):(\d{ 1,2 })$/;
        const r: RegExpMatchArray | null = dateStr.match(reg);
        if (r === null) { return false };
        r[2] = `${parseInt(r[2],10) - 1}`;
        const d:Date = new Date(parseInt(r[1],10), parseInt(r[2],10), parseInt(r[3],10), parseInt(r[4],10), parseInt(r[5],10), parseInt(r[6],10));
        if (`${d.getFullYear()}` !== r[1]) { return false };
        if (`${d.getMonth()}` !== r[2]) { return false };
        if (`${d.getDate()}` !== r[3]) { return false };
        if (`${d.getHours()}` !== r[4]) { return false };
        if (`${d.getMinutes()}` !== r[5]) { return false };
        if (`${d.getSeconds()}` !== r[6]) { return false };

        return true;
    }
    /**
     * 分解日期返回obj
     * @param date Date
     */
    public datePart(date: Date): IDateOb {
        const dateInfo: IDateOb = {
            year: date.getFullYear(),// 年
            month: date.getMonth() + 1,// 月
            date: date.getDate(),// 日期
            hours: date.getHours(),// 小时
            minutes: date.getMinutes(),// 分钟
            seconds: date.getSeconds(),// 秒
            day: date.getDay(),// 周几
        };

        return dateInfo;
    }
}